package com.bjy.qa.agent.tools.juel;

import com.bjy.qa.agent.tools.SpringTool;
import de.odysseus.el.ExpressionFactoryImpl;
import de.odysseus.el.util.SimpleContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.el.ExpressionFactory;
import javax.el.ValueExpression;
import java.util.Map;

public class JuelHelper {
    private static final Logger logger = LoggerFactory.getLogger(Param.class);

    public static final JuelConf juelConf; // Juel 配置信息

    static {
        juelConf = SpringTool.getBean(JuelConf.class);
        logger.info("Juel 配置信息：{}", juelConf);
    }

    /**
     * 获取扩展的 SimpleContext
     * @return
     */
    private static SimpleContext getExtendSimpleContext() {
        SimpleContext context = new SimpleContext();

        try {
            context.setFunction("auth", "basic", Auth.class.getMethod("basic", String.class, String.class)); // basic 认证
            context.setFunction("auth", "sign_jwt", Auth.class.getMethod("sign_JWT", String[].class));
            context.setFunction("auth", "sign_brtc", Auth.class.getMethod("signBJY_BRTC", String.class, String.class, String.class, String.class, long.class, long.class)); // BJY BRTC 签名
            context.setFunction("auth", "sign_brtc_fast", Auth.class.getMethod("signBJY_BRTC", String.class, String.class, String.class, String.class)); // BJY BRTC 签名（无需输入 时间戳、 有效期）
            context.setFunction("param", "escape", Param.class.getMethod("escape", String.class)); // 转义
            context.setFunction("param", "unescape", Param.class.getMethod("unescape", String.class)); // 反转义
            context.setFunction("param", "timestamp", Param.class.getMethod("timestamp", String.class)); // 时间戳
            context.setFunction("param", "date", Param.class.getMethod("date", String.class)); // 日期时间
            context.setFunction("param", "string", Param.class.getMethod("string", int.class)); // 字符串
            context.setFunction("param", "special_string", Param.class.getMethod("specialString", int.class)); // 特殊字符串
            context.setFunction("param", "random", Param.class.getMethod("random", int.class)); // 随机数
        } catch (NoSuchMethodException e) {
            throw new RuntimeException(e);
        }

        return context;
    }

    /**
     * 将表达式中的变量占位符用 variableMap 中的变量值替换，并生成完整字符串返回
     * @param argMap 变量 map
     * @param expression 表达式
     * @return
     */
    public static String getValue(Map argMap, String expression) {
        ExpressionFactory factory = new ExpressionFactoryImpl();
        SimpleContext context = JuelHelper.getExtendSimpleContext();

        for (Object key : argMap.keySet()) {
            // TODO: 2023/8/9 临时改成 string 类型遇到 \r\n 转义成 \\r\\n，按道理 form 表单或 json 提交都需要转义，所以先这么改，后续要是有问题再改成根据配置是不是转义
            if (argMap.get(key) instanceof String) {
                context.setVariable(key.toString(), factory.createValueExpression(Param.escape(argMap.get(key).toString()), Object.class));
            } else {
                context.setVariable(key.toString(), factory.createValueExpression(argMap.get(key), Object.class));
            }
        }

        ValueExpression valueExpression = factory.createValueExpression(context, expression, String.class);
        return valueExpression.getValue(context).toString();
    }
}
